package com.keeping.aiimagery.websocket;

import com.keeping.aiimagery.entity.ChatRecord;
import com.keeping.aiimagery.entity.enums.MsgType;
import com.keeping.aiimagery.handler.strategy.ChatMessageContext;
import com.keeping.aiimagery.service.ChatRecordService;
import com.keeping.aiimagery.service.ChatRoomService;
import com.keeping.aiimagery.service.UserService;
import com.keeping.aiimagery.service.impl.ChatRecordServiceImpl;
import com.keeping.aiimagery.service.impl.ChatRoomServiceImpl;
import com.keeping.aiimagery.service.impl.UserServiceImpl;
import com.keeping.aiimagery.util.StrUtils;
import com.unfbx.chatgpt.OpenAiStreamClient;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * 描述：websocket 服务端
 *
 * @author Ranger
 * @date 2023-03-23
 */
@Slf4j
@Component
@ServerEndpoint("/websocket/{rid}/{uid}")
public class WebSocketServer {

    private static ApplicationContext applicationContext;

    private static OpenAiStreamClient openAiStreamClient;

    private UserService userService;

    private ChatRoomService chatRoomService;
    private ChatRecordService chatRecordService;

    @Autowired
    public void setOrderService(OpenAiStreamClient openAiStreamClient) {
        this.openAiStreamClient = openAiStreamClient;
    }

    public static void setApplicationContext(ApplicationContext applicationContext) {
        WebSocketServer.applicationContext = applicationContext;
    }

    //在线总数
    private static int onlineCount;
    //当前会话
    private Session session;
    //用户id -目前是按浏览器随机生成
    private String uid;
    //房间id
    private String rid;
    //初始房间 id
    private static String d_rid = "0";

    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();

    /**
     * 用来存放每个客户端对应的WebSocketServer对象
     */
    private static ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap();

    /**
     * 为了保存在线用户信息，在方法中新建一个list存储一下【实际项目依据复杂度，可以存储到数据库或者缓存】
     */
    private final static List<Session> SESSIONS = Collections.synchronizedList(new ArrayList<>());


    /**
     * 建立连接
     *
     * @param session
     * @param uid
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("uid") String uid, @PathParam("rid") String rid) {
        this.session = session;
        this.uid = uid;
        this.rid = rid;
        webSocketSet.add(this);
        SESSIONS.add(session);
        if (webSocketMap.containsKey(StrUtils.getWebSocketKey(uid, rid))) {
            webSocketMap.remove(StrUtils.getWebSocketKey(uid, rid));
            webSocketMap.put(StrUtils.getWebSocketKey(uid, rid), this);
        } else {
            webSocketMap.put(StrUtils.getWebSocketKey(uid, rid), this);
            addOnlineCount();
        }
        log.info("[连接用户ID:{},roomId:{}] 建立连接, 当前连接数:{}", this.uid, this.rid, getOnlineCount());
    }

    /**
     * 断开连接
     */
    @OnClose
    public void onClose() {
        webSocketSet.remove(this);
        if (webSocketMap.containsKey(StrUtils.getWebSocketKey(uid, rid))) {
            webSocketMap.remove(StrUtils.getWebSocketKey(uid, rid));
            subOnlineCount();
        }
        log.info("[连接ID:{},roomId:{}] 断开连接, 当前连接数:{}", uid, rid, getOnlineCount());
    }

    /**
     * 发送错误
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.info("[连接ID:{},roomId:{}] 错误原因:{}", this.uid, this.rid, error.getMessage());
        error.printStackTrace();
    }

    /**
     * 接收到客户端消息
     *
     * @param msg
     */
    @SneakyThrows
    @OnMessage
    public void onMessage(String msg) {
        log.info("[房间ID:{}],[用户ID:{}] 收到消息:{}", this.rid, this.uid, msg);
        userService = applicationContext.getBean(UserServiceImpl.class);
        chatRoomService = applicationContext.getBean(ChatRoomServiceImpl.class);
        chatRecordService = applicationContext.getBean(ChatRecordServiceImpl.class);
        chatRoomService.saveRoom(this.rid, this.uid, msg);

        //保存用户聊天记录
        ChatRecord build = ChatRecord.builder().message(msg).msgType(MsgType.USER).roomId(Long.valueOf(rid)).build();
        build.created(Long.valueOf(uid));
        chatRecordService.save(build);

        ChatMessageContext context = new ChatMessageContext(session, this.uid, this.rid, msg);
        context.sendText();
    }


    /**
     * 获取当前连接数
     *
     * @return
     */
    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    /**
     * 当前连接数加一
     */
    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }

    /**
     * 当前连接数减一
     */
    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }

}

